﻿//TODO: Test implementation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// 
    /// </summary>
    public enum DETECTION_MODE
    {
        /// <summary>
        /// 
        /// </summary>
        EXPERIMENTAL,
        /// <summary>
        /// 
        /// </summary>
        METHOD1
    }

    /// <summary>
    /// Contains one of the types that might be returned by the detection algorithm.
    /// </summary>
    public enum DETECTED_TYPE
    {
        DATAMATRIXCODE,    
        BARCODE
    }

    /// <summary>
    /// Barcode enhancement filter. Tries to enhance Barcode.
    /// </summary>
    public class BarcodeFilter : BaseForeBackgroundColorFilter
    {
        protected int m_nThreshold = 90;
        protected bool m_bOnlyThreshold = false;

        /// <summary>
        /// Barcodefilter default constructor
        /// </summary>
        public BarcodeFilter()
        {
        }

        /// <summary>
        /// Use this to specify a threshold
        /// </summary>
        /// <param name="_nThreshold"></param>
        public BarcodeFilter(int _nThreshold)
            : this(_nThreshold, false)
        {

        }

        /// <summary>
        /// Use this to specify a concrete threshold.
        /// Only THIS concrete value will be taken
        /// </summary>
        /// <param name="_nThreshold"></param>
        /// <param name="_bOnlyThreshold"></param>
        public BarcodeFilter(int _nThreshold, bool _bOnlyThreshold)
        {
            m_nThreshold = _nThreshold;
            m_bOnlyThreshold = _bOnlyThreshold;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_barCodeFilter"></param>
        internal BarcodeFilter(BarcodeFilter _barCodeFilter)
        {
            this.m_nThreshold = _barCodeFilter.m_nThreshold;
            this.m_bOnlyThreshold = _barCodeFilter.m_bOnlyThreshold;
        }

        /// <summary>
        /// Sets or gets the threshold
        /// </summary>
        public int Threshold
        {
            get { return m_nThreshold; }
            set { m_nThreshold = value; }
        }

        /// <summary>
        /// Sets or gets if only this threshold should be used.
        /// </summary>
        public bool OnlyThisThreshold
        {
            get { return m_bOnlyThreshold; }
            set { m_bOnlyThreshold = value; }
        }

        /// <summary>
        /// Execute this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;

            switch(DETECTION_MODE.EXPERIMENTAL)
            {
                case DETECTION_MODE.EXPERIMENTAL:
                    NewMethod(bitmap);
                    break;

                default:
                    Method1(bitmap);
                    break;
            }

            return _bitmap;
        }

        /// <summary>
        /// This is another method to get a barcode
        /// </summary>
        /// <param name="_bitmap"></param>
        private void NewMethod(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;
            List<Color> aColor = new List<Color>();
            int y = 0;
            int x = 0;

            int nCount = 0;
            aColor.Add(bitmap.GetPixel(x, y));
            aColor.Add(bitmap.GetPixel(x, y));
            nCount++;

            Color colorToSet = Color.Transparent;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            int nAverageR = -1;
            int nAverageG = -1;
            int nAverageB = -1;

            Color color = Color.Transparent;
            for (y = 0; y < nHeight; y++)
            {
                int nCountAvg = 0;
                for (x = 0; x < nWidth; x++)
                {
                    nCountAvg++;
                    color = bitmap.GetPixel(x, y);
                    nAverageR = color.R;
                    nAverageG = color.G;
                    nAverageB = color.B;
                    aColor.Add(color);
                    Color colorPrev = aColor[nCount - 1];
                    Color colorCurrent = aColor[nCount];

                    Color colorAvg = Color.FromArgb(nAverageR / nCountAvg, nAverageG / nCountAvg, nAverageB / nCountAvg);
                    int nRGBSum = ColorFunctions.RGBChannelSum(colorAvg);

                    if (m_bOnlyThreshold)
                    {
                        if (nRGBSum == m_nThreshold)
                        {
                            colorToSet = m_ColorForeground;
                            nCountAvg = 0;
                        }
                        else
                        {
                            colorToSet = m_ColorBackground;
                        }
                    }
                    else
                    {
                        if (nRGBSum > m_nThreshold)
                        {
                            colorToSet = m_ColorForeground;
                            nCountAvg = 0;
                        }
                        else
                        {
                            colorToSet = m_ColorBackground;
                        }
                    }
                    bitmap.SetPixel(x, y, colorToSet);
                    nCount++;
                }
            }
        }

        //TODO: implement Barcodefilter, Method1
        /// <summary>
        /// Another one to get a threshold
        /// </summary>
        /// <param name="_bitmap"></param>
        private void Method1(UnsafeBitmap _bitmap)
        {
        }

        /// <summary>
        /// Use this to clone the filter
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new BarcodeFilter(this);
        }
    }
}
